//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace OpenLS.Chart.UI
{
    class MarkerStyleSizeToPathDataConverter: IMultiValueConverter
    {
        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            MarkerStyle? style = StrictConverter.Convert<MarkerStyle?>( values[0], null);
            double diameter = StrictConverter.Convert(values[1], Marker.DefaultSize);
            if (style == null)
                style = GetMarkerStyleFromIndex(StrictConverter.Convert(values[2], 0));
            return new PathGeometry(GetFigures(style.Value, diameter));
        }
        internal static MarkerStyle GetMarkerStyleFromIndex (int index)
        {
            switch (index % 9)
            {
                case 0:
                    return MarkerStyle.Square;
                case 1:
                    return MarkerStyle.Diamond;
                case 2:
                    return MarkerStyle.Triangle;
                case 3:
                    return MarkerStyle.X;
                case 4:
                    return MarkerStyle.Star;
                case 5:
                    return MarkerStyle.Dot;
                case 6:
                    return MarkerStyle.Dash;
                case 7:
                    return MarkerStyle.Circle;
                case 8:
                    return MarkerStyle.Plus;
                    default:
                    throw new NotSupportedException();
                
            }
        }

        private static IEnumerable<PathFigure> GetFigures(MarkerStyle style, double diameter)
        {
            double halfDiameter = diameter/2;
            var halfSize = new Size(diameter/2, diameter/2);
            switch (style)
            {
                case MarkerStyle.None:
                    yield break;
                case MarkerStyle.Circle:
                    yield return
                        new PathFigure(new Point(diameter/2, 0),
                                       new List<PathSegment>
                                           {
                                               new ArcSegment(new Point(diameter/2, diameter), halfSize, 180, true,
                                                              SweepDirection.Clockwise, true),
                                               new ArcSegment(new Point(diameter/2, 0), halfSize, 180, true,
                                                              SweepDirection.Clockwise, true)
                                           }, true);
                    break;
                case MarkerStyle.Square:
                    yield return new PathFigure(new Point(0, 0), new List<PathSegment>
                                                                     {
                                                                         new LineSegment(new Point(diameter, 0), true),
                                                                         new LineSegment(new Point(diameter, diameter),
                                                                                         true),
                                                                         new LineSegment(new Point(0, diameter), true),
                                                                     }, true);
                    break;
                case MarkerStyle.Diamond:
                    yield return new PathFigure(
                        new Point(halfDiameter, 0),
                        new List<PathSegment>
                            {
                                new LineSegment(new Point(diameter, halfDiameter), true),
                                new LineSegment(new Point(halfDiameter, diameter), true),
                                new LineSegment(new Point(0, halfDiameter), true),
                            }
                        , true
                        );
                    break;
                case MarkerStyle.X:
                    yield return new PathFigure(new Point(0, 0),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(diameter, diameter), true),
                                                    },
                                                true);
                    yield return new PathFigure(new Point(diameter, 0),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(0, diameter), true),
                                                    },
                                                true);
                    break;
                case MarkerStyle.Plus:
                    yield return new PathFigure(new Point(halfDiameter, 0),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(halfDiameter, diameter), true)
                                                    },
                                                true);
                    yield return new PathFigure(new Point(0, halfDiameter),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(diameter, halfDiameter), true)
                                                    },
                                                true);
                    break;
                case MarkerStyle.Triangle:
                    yield return new PathFigure(new Point(halfDiameter, 0),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(diameter, diameter), true),
                                                        new LineSegment(new Point(0, diameter), true),
                                                    }, true);
                    break;
                case MarkerStyle.Star:
                    yield return new PathFigure(new Point(0, 0),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(diameter, diameter), true),
                                                    },
                                                true);
                    yield return new PathFigure(new Point(diameter, 0),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(0, diameter), true),
                                                    },
                                                true);
                    yield return new PathFigure(new Point(halfDiameter, 0),
                                                new List<PathSegment>
                                                    {
                                                        new LineSegment(new Point(halfDiameter, diameter), true)
                                                    },
                                                true);
                    break;

                case MarkerStyle.Dash:
                    {
                        double diameter8 = diameter/8;
                        yield return new PathFigure(new Point(0, halfDiameter - diameter8),
                                                    new List<PathSegment>
                                                        {
                                                            new LineSegment(
                                                                new Point(diameter, halfDiameter - diameter8),
                                                                true),
                                                            new LineSegment(
                                                                new Point(diameter, halfDiameter + diameter8),
                                                                true),
                                                            new LineSegment(new Point(0, halfDiameter + diameter8), true),
                                                        },
                                                    true);
                    }
                    break;
                case MarkerStyle.Dot:
                    {
                        double diameter8 = diameter/8;
                        yield return new PathFigure(new Point(halfDiameter, halfDiameter - diameter8),
                                                    new List<PathSegment>
                                                        {
                                                            new LineSegment(
                                                                new Point(diameter, halfDiameter - diameter8),
                                                                true),
                                                            new LineSegment(
                                                                new Point(diameter, halfDiameter + diameter8),
                                                                true),
                                                            new LineSegment(
                                                                new Point(halfDiameter, halfDiameter + diameter8), true),
                                                        },
                                                    true);
                    }
                    break;
                default:
                    throw new NotSupportedException();
            }
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        #endregion
    }
}
